home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
038a
/
aplibs91.zip
/
MISC-U.BAS
< prev
next >
Wrap
BASIC Source File
|
1991-07-01
|
19KB
|
656 lines
' ╔════════════════════════════╗
' ║ ║
' ║ MISC_U.BAS ║
' ║ ║
' ║ H.B. LIBRARY LEFTOVERS ║
' ║ ║
' ╚════════════════════════════╝
$COMPILE UNIT
$ERROR ALL OFF
DEFINT A-Z
%False = 0
%True = NOT %False
%FLAGS = 0: %AX = 1: %BX = 2: %CX = 3: %DX = 4
%SI = 5: %DI = 6: %BP = 7: %DS = 8: %ES = 9
%LtButton = 0
%RtButton = 1
%ReadMotionCounters = &H0B
%ResetRodent = 00
%ReadRodent = 03
%CountClicks = 05
%CountReleases = 06
' MENU RETURN CODES (KEY PRESSED.)
%CR = 0: %Esc = &H20: %F1 = &H100: %F2 = &H200
%PgUp = &H400: %PgDn = &H600
%RArrow = &H800: %LArrow = &HA00
%CheckScreensSaved = %False
DECLARE SUB SUPERMENU (string array,integer,integer,integer,string,integer)
DECLARE SUB BOXMESSAGE (integer, integer, integer)
DECLARE SUB QBox (integer, integer, integer, string, integer)
DECLARE SUB ENTERSTRING (string, integer, string)
DECLARE SUB ENTERYESNO (integer)
DECLARE SUB ENTERNUMBER (double, string, string)
DECLARE SUB Marker (string)
EXTERNAL Footer$, CurrLine, LineGroup, Page%, NewRec, KeyField, PullDown
EXTERNAL OopsBeep$, InitPrt$, FontCode$, NextScrn2Pop, ScrnStackSize
EXTERNAL ScreenStack$ (), VideoSeg&, OrigL, OrigC, ReverseLF$, NeedDCon
EXTERNAL MenuHelpLine$(), TopMargin, BottomMargin, Header$
EXTERNAL FldColor, ScrColor, GraphicsChrSetOn$, GraphicsChrSetOff$, BoldPrtOn$
EXTERNAL BoldPrtOff$, ItalicPrtOn$, ItalicPrtOff$, RegPrt$, FastPrt$
EXTERNAL WidePrt$, BigPrtOn$, BigPrtOff$, LQPrt$, DraftPrt$
EXTERNAL MicroPrtOn$, MicroPrtOff$, ElitePrt$, PicaPrt$
EXTERNAL LBPresses, LBReleases, LeftButtonPressed
EXTERNAL RightButtonPressed, MouseLin, MouseCol, FlashBox
' _____________________________________________________
SUB SCREENPUSH PUBLIC
DEF SEG = VideoSeg&
INCR NextScrn2Pop
$IF %CheckScreensSaved
FOR N = 1 TO 9: LPRINT ReverseLF$;: NEXT
LPRINT "SCREEN PUSHED: "; NextScrn2Pop
FOR N = 1 TO 9: LPRINT: NEXT
$ENDIF
IF NextScrn2Pop =< ScrnStackSize THEN
ScreenStack$ (NextScrn2Pop) = PEEK$ (0, 4000)
ELSE
BSAVE RD$ + "SCRN_" + LTRIM$(STR$(NextScrn2Pop)), 0, 4000
END IF
DEF SEG
END SUB REM PUSHSCREEN
' _____________________________________________________
SUB SCREENPOP PUBLIC
DEF SEG = VideoSeg&
$IF %CheckScreensSaved
FOR N = 1 TO 9: LPRINT ReverseLF$;: NEXT
LPRINT " SCREEN POPPED: "; NextScrn2Pop
FOR N = 1 TO 9: LPRINT: NEXT
$ENDIF
IF NextScrn2Pop < 1 THEN
FOR N = 1 TO 10: LOCATE 2*N, 5*N: PRINT "SCREEN STACK UNDERFLOW": NEXT
ELSEIF NextScrn2Pop =< ScrnStackSize THEN
POKE$ 0, ScreenStack$ (NextScrn2Pop)
ELSE
BLOAD RD$ + "SCRN_" + LTRIM$(STR$(NextScrn2Pop))
END IF
DECR NextScrn2Pop
DEF SEG
END SUB REM POPSCREEN
' _____________________________________________________
SUB RestoreDOSScreen PUBLIC
NextScrn2Pop = 1
CALL SCREENPOP
LOCATE OrigL, 1
END SUB
' =============================================================================
SUB PRINTLINE (L$) PUBLIC
LOCAL I, L0, C0, Att0
STATIC NL, Destination
%PageLength = 66
IF INKEY$ = CHR$(27) THEN
L$ = "ABORTED BY USER"
IF Destination > 0 THEN CLOSE Destination
EXIT SUB
END IF
' Line comes in as a passed string. Increase line counter ...
INCR CurrLine
IF UCASE$ (L$) = "START" THEN ' initialization of print job
NL = %PageLength - TopMargin - BottomMargin ' (these vars are o.k.)
IF Footer$ <> "" THEN DECR NL, 2
IF Header$ <> "" THEN DECR NL, 2
L0 = CSRLIN: C0 = POS: Att0 = SCREEN (CSRLIN, POS, 1)
CALL Out2Where (Destination)
LOCATE L0, C0: COLOR Att0 MOD 16, Att0 \ 16
IF Destination = 0 THEN L$ = "ABORTED BY USER": EXIT SUB
CurrLine = 1
Page% = 1
PRINT #32766, "" ' detect printer error before sending any data
PRINT #32766, InitPrt$ + FontCode$;
FOR I = 1 TO TopMargin: PRINT #32766,"" : NEXT
' If page is full, or doesn't have room for LineGroup lines, print footer ...
ELSEIF CurrLine + LineGroup > NL OR UCASE$ (L$) = "END" THEN
IF Footer$ <> "" THEN GOSUB PPrintFoot
INCR Page%: CurrLine = 1: PRINT #32766, CHR$(12) ' ... form feed ...
' ... and if there's more to print, also a header ...
IF UCASE$(L$) <> "END" AND Header$ <> "" THEN_
FOR I = 1 TO TopMargin: PRINT #32766,"" : NEXT: GOSUB PPrintHead
END IF
' now print the line and exit
IF UCASE$(L$) = "END" THEN
Page% = 0
PRINT #32766, InitPrt$;
ELSEIF UCASE$(L$) <> "START" THEN
PRINT #32766, L$
END IF
EXIT SUB
PPrintHead:
PRINT #32766, Header$;
IF INSTR (UCASE$ (RIGHT$(Header$,8)), "PAGE") THEN
PRINT #32766, Page%
ELSE
PRINT #32766,
END IF
PRINT #32766,
RETURN
PPrintFoot:
PRINT #32766,
PRINT #32766, Footer$;
IF INSTR (UCASE$ (RIGHT$(Footer$,8)), "PAGE") THEN
PRINT #32766, Page%
ELSE
PRINT #32766,
END IF
RETURN
END SUB REM PRINTLINE
'≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
SUB Out2Where (Destination) SHARED
LOCAL Fl$, Appending, MLine$
DIM MLine$ (8)
CALL SCREENPUSH
MLine$ (1) = "P SEND OUTPUT TO THE PRINTER"
MLine$ (2) = "D SEND OUTPUT TO A DISK FILE"
MLine$ (3) = "END"
Choice = 1
CALL SUPERMENU (MLine$ (), 0, 30, Choice, "PRINT TO WHERE", Ky%)
IF Ky% = %Esc THEN Destination = 0: CALL SCREENPOP: EXIT SUB
Destination = 32766
SELECT CASE LEFT$ (MLine$ (Choice), 1)
CASE "P"
IF InitPrt$ = "" THEN
Stpd:
DATA "PRINTER FORMATTING CODES HAVE BEEN REMOVED FROM MEMORY."
DATA ""
DATA "TO USE PRINTER PLEASE EXIT FORM THIS PROGRAM AND RE-START IT"
DATA END
RESTORE Stpd
CALL BOXMESSAGE (0,0,3)
Destination = 0: CALL SCREENPOP: EXIT SUB
END IF
OPEN "LPT1:" FOR OUTPUT AS 32766
CALL QBox (16,0,1,"CHECK THE PRINTER AND PRESS ANY KEY WHEN IT'S READY",0)
DO: LOOP UNTIL INSTAT
IF INKEY$ = CHR$(27) THEN
CLOSE 32766
Destination = 0
CALL SCREENPOP
EXIT SUB
END IF
CASE "D"
CALL QBox (16, 0, 1, "NAME OF FILE TO SEND OUTPUT TO", 20)
Fl$ = "PRINT.OUT"
Msg$ = "Caps"
COLOR FldColor MOD 16, FldColor \ 16
CALL ENTERSTRING (Fl$, 20, Msg$)
Fl$ = REMOVE$ (Fl$, ANY "?*|<>,+=/ ")
IF RTRIM$ (Fl$) = "" OR Msg$ = "ESC" _
THEN Destination = 0: CALL SCREENPOP: EXIT SUB
IF DIR$ (Fl$) <> "" THEN
CALL SCREENPUSH
COLOR ScrColor MOD 16, ScrColor \ 16
CLS
MLine$ (1) = "A ADD ONTO END OF EXISTING FILE " + Fl$
MLine$ (2) = "E ERASE AND REPLACE EXISTING FILE " + Fl$
MLine$ (3) = "END"
CALL SUPERMENU (MLine$ (), 0, 30, Choice,_
"File " + LCASE$ (Fl$) + "already exists", Ky%)
IF Choice = 0 THEN Destination = 0: CALL SCREENPOP: EXIT SUB
Appending = Choice - 2
CALL SCREENPOP
END IF
IF Appending THEN
OPEN Fl$ FOR APPEND AS #32766
ELSE
OPEN Fl$ FOR OUTPUT AS #32766
END IF
CALL QBox (17, 0, 1,_
"REMOVE FORMATTING CODES AND MAKE A STRAIGHT ASCII FILE ?", 1)
StripEm = %False
CALL ENTERYESNO (StripEm)
IF StripEm THEN
BEEP: DELAY 1: BEEP: DELAY 1: BEEP
BigPrtOff$ = ""
BigPrtOn$ = ""
BoldPrtOff$ = ""
BoldPrtOn$ = ""
DraftPrt$ = ""
ElitePrt$ = ""
FastPrt$ = ""
GraphicsChrSetOff$ = ""
GraphicsChrSetOn$ = ""
InitPrt$ = ""
ItalicPrtOff$ = ""
ItalicPrtOn$ = ""
LQPrt$ = ""
MicroPrtOff$ = ""
MicroPrtOn$ = ""
PicaPrt$ = ""
RegPrt$ = ""
WidePrt$ = ""
END IF
END SELECT
CALL SCREENPOP
ERASE MLine$
END SUB
'≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
FUNCTION GetAttr PUBLIC
DEF SEG = VideoSeg&
GetAttr = PEEK ((80*CSRLIN-80 + POS - 1) * 2) + 1
DEF SEG
END FUNCTION
'≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
FUNCTION IsRodent PUBLIC ' finds if you have a rodent and also resets it
REG %AX, %ResetRodent
CALL INTERRUPT &H33
IsRodent = REG(%AX) ' true if present
END FUNCTION
'≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
SUB Mouse(MV1, MV2, MV3, MV4) PUBLIC
REG %AX, MV1: REG %BX, MV2: REG %CX, MV3: REG %DX, MV4
CALL INTERRUPT &H33
MV1 = REG(%AX): MV2 = REG(%BX): MV3 = REG(%CX): MV4 = REG(%DX)
END SUB
' _________________________________________________________________________
FUNCTION MouseClicked PUBLIC
LOCAL MC, X, Y
IF NeedDCon THEN
CALL Mouse (%ReadRodent, MC, X, Y)
MouseClicked = MC
ELSE
MouseClicked = 0
END IF
END FUNCTION
' _________________________________________________________________________
SUB GetMouse SHARED PUBLIC
' %CountReleases = 6 ' / BX=0 (ON RETURN, BX = NUMBER OF REL) READ INTO BX
REG (%AX), %CountClicks
REG (%BX), %LtButton
CALL INTERRUPT &H33
LBPresses = LBPresses + REG (%BX)
REG (%AX), %CountReleases
REG (%BX), %LtButton
CALL INTERRUPT &H33
LeftButtonReleases = LeftButtonReleases + REG (%BX)
REG (%AX), %ReadRodent
CALL INTERRUPT &H33
LeftButtonPressed = (REG (%BX) = 1)
RightButtonPressed = (REG (%BX) > 1)
MouseCol = REG (%CX) \ 8
MouseLin = REG (%DX) \ 8
END SUB
' _________________________________________________________________________
SUB MouseControl (HMick, VMick) PUBLIC
CALL SCREENPUSH
IF HMick = 0 THEN
CALL QBox (11, 0, 1, "How many mickeys / 8 pixels HORIZONTAL ? ", 2)
A# = 12
CALL ENTERNUMBER (A#, "##", Msg$)
IF Msg$ <> "CR" THEN EXIT SUB
HMick = A#
END IF
IF VMick = 0 THEN
CALL QBox (13, 32, 1, "How many mickeys / 8 pixels VERTICAL ? ", 2)
A# = 32
CALL ENTERNUMBER (A#, "##", Msg$)
IF Msg$ <> "CR" THEN EXIT SUB
VMick = A#
END IF
REG %AX, &H000F ' AX = 000Fh
REG %CX, HMick ' CX = number of mickeys per 8 pixels horiz
REG %DX, VMick ' DX = number of mickeys per 8 pixels vert
CALL INTERRUPT &H33 ' INT 33 - MS MOUSE - DEFINE MICKEY/PIXEL RATIO
FlashBox = %True
CALL QBox (21, 60, 1, "MOUSE DRIVER RESET", 0)
DELAY 1
CALL SCREENPOP
END SUB
FUNCTION GetCurrentDrive$ PUBLIC
REG %AX, &H1900
CALL INTERRUPT &H21
GetCurrentDrive$ = CHR$ ((REG (%AX) AND &B00001111) + 65) + ":"
END FUNCTION
FUNCTION GetCurrentDir$ (Drv$) PUBLIC
STATIC Dummy$
Dummy$ = SPACE$ (64)
REG %AX, &H4700
IF Drv$ = "" THEN
REG %DX, 0 ' for default drive
ELSE
REG %DX, (ASC(UCASE$(Drv$))-64)
END IF
REG %DS, STRSEG (Dummy$)
REG %SI, STRPTR (Dummy$)
CALL INTERRUPT &H21
GetCurrentDir$ = "\" + EXTRACT$ (Dummy$, CHR$(0))
END FUNCTION ' ========================== GetCurrentDir$ ()
FUNCTION GetFreeSpace! (Drv$) PUBLIC
IF Drv$ = "" THEN
REG %DX, 0 ' for default drive
ELSE
REG %DX, (ASC(UCASE$(Drv$))-64)
END IF
REG %AX, &H3600 ' dos function number &H36 into AH
CALL INTERRUPT &H21
GetFreeSpace! = CSNG (REG(%BX)) * REG (%CX) * REG (%AX)
' free clusters * byt/sect * sect/cluster
END FUNCTION ' ----------
FUNCTION ReadParamFor (A$) PUBLIC ' this reads parameters from the command tail
LOCAL L, N
L = INSTR (COMMAND$, A$)
IF L THEN
N = VAL ("&H"+MID$ (COMMAND$, L + 5, 2))
IF N THEN ReadParamFor = N
END IF
END FUNCTION ' ----------
SUB ClearLine PUBLIC
LOCAL CLL0, CLC0
CLL0 = CSRLIN
CLC0 = POS
PRINT STRING$ ((81-CLC0)," ");
LOCATE CLL0, CLC0
END SUB ' ----------
' ============================================================================
SUB DirFirst (F$, FileSize&, DateCode&, TimeCode&) PUBLIC
LOCAL DTASeg&, AttrOffset&, FlNOffset&, SearchErr, FlN$, N
FlN$ = F$ + CHR$(0)
REG %DS, STRSEG (FlN$)
REG %DX, STRPTR (FlN$)
REG %CX, &H17
REG %AX, &H4E00
CALL INTERRUPT &H21
SearchErr = REG(%AX)
IF SearchErr THEN
F$ = ""
EXIT SUB
END IF
REG %AX, &H2F00
CALL INTERRUPT &H21
DTAseg& = REG(%ES)
AttrOffset& = REG(%BX) + &H15
FlNOffset& = REG(%BX) + &H1E
TimeOffset& = REG(%BX) + &H16
DateOffset& = REG(%BX) + &H18
SizeOffset& = REG(%BX) + &H1A
FlN$ = ""
DEF SEG = DTAseg&
N = 0
DO UNTIL PEEK (FlNOffset& + N) = 0 ' read the ASCIIZ file-name string
FlN$ = FlN$ + CHR$ (PEEK (FlNOffset& + N))
INCR N
LOOP
IF (PEEK(AttrOffset&) AND 16) = 16 THEN ' bracket if a subdirectory
FlN$ = "<"+FlN$+">"
END IF
FileSize& = CVL (PEEK$ (SizeOffset&, 4))
DateCode& = PEEK (DateOffset&) + &H100 * PEEK (DateOffset& + 1)
TimeCode& = PEEK (TimeOffset&) + &H100 * PEEK (TimeOffset& + 1)
DEF SEG
F$ = FlN$
END SUB
' ===========================
SUB DirNext (F$, FileSize&, DateCode&, TimeCode&) PUBLIC
LOCAL FlN$, DTAseg&, FlNOffset&, AttrOffset&, N
REG %AX, &H4F00
CALL INTERRUPT &H21
IF REG(%AX) = 18 THEN
F$ = ""
EXIT SUB
END IF
REG %AX, &H2F00
CALL INTERRUPT &H21
DTAseg& = REG(%ES)
AttrOffset& = REG(%BX) + 21
FlNOffset& = REG(%BX) + &H1E
TimeOffset& = REG(%BX) + &H16
DateOffset& = REG(%BX) + &H18
SizeOffset& = REG(%BX) + &H1A
FlN$ = ""
DEF SEG = DTAseg&
DO UNTIL PEEK (FlNOffset& + N) = 0
FlN$ = FlN$ + CHR$(PEEK(FlNOffset& + N))
INCR N
LOOP
IF (PEEK(AttrOffset&) AND 16) = 16 THEN
FlN$ = "<"+FlN$+">" ' subdirs will come back w/ brackets
END IF
FileSize& = CVL (PEEK$ (SizeOffset&, 4))
DateCode& = PEEK (DateOffset&) + &H100 * PEEK (DateOffset& + 1)
TimeCode& = PEEK (TimeOffset&) + &H100 * PEEK (TimeOffset& + 1)
DEF SEG
F$ = FlN$
END SUB
' ========================================
FUNCTION DecodeDate$ (DateCode&) PUBLIC
LOCAL M, D, Y
Y = DateCode&\512
M = (DateCode& MOD 512) \ 32
D = DateCode& MOD 32
DecodeDate$ = LTRIM$ (STR$ (M)) + "-" +_
STRING$ (1 + (D > 9), "0") + LTRIM$ (STR$ (D)) + "-" +_
LTRIM$ (STR$ (Y + 80))
END FUNCTION ' ============================ DecodeDate$ ()
FUNCTION DecodeTime$ (TimeCode&) PUBLIC
LOCAL H, H24, M
H24 = INT(TimeCode&\2048)
IF H24 > 12 THEN
H = H24 - 12
pm = %True
ELSE
H = H24
pm = %False
END IF
IF H = 0 THEN H = 12
M = (TimeCode&-(CLNG(H24)*2048))\32
DecodeTime$ = STRING$ (1 + (H > 9), " ") + LTRIM$ (STR$ (H)) + ":" +_
STRING$ (1 + (M > 9), "0") + LTRIM$ (STR$ (M)) +_
MID$ (" pm am", pm*3+4, 3)
END FUNCTION ' ============================ DecodeTime$ ()
FUNCTION EXIST (F$) PUBLIC
LOCAL SearchErr, FZ$
REG %AX, &H2F00
CALL INTERRUPT &H21 ' GET DOS'S D.T.A.
' (in FEXIST.BOX Barry gets out the DTA addr but
' never uses it. It's ES:BX.)
FZ$ = F$ + CHR$(0)
REG %DS, STRSEG (FZ$)
REG %DX, STRPTR (FZ$)
REG %CX, &H7
REG %AX, &H4E00
CALL INTERRUPT &H21
SearchErr = REG(%AX)
SELECT CASE SearchErr
CASE 2, 3, 15, 18
EXIST = 0
CASE ELSE
EXIST = -1
END SELECT
DEF SEG
END Function ' ================== EXIST ()
FUNCTION FQFileSpec$ (A$) PUBLIC
LOCAL CurrentDir$, CurrentDrv$ ' Of course there's a DOS function
CurrentDrv$ = GetCurrentDrive$ ' that does something like this --
CurrentDir$ = GetCurrentDir$ ("") ' maybe exactly this! I never did
' try it out. So this may be the
A$ = REMOVE$ (A$, " ") ' hard way!
IF INSTR (A$, ANY "^/,<>+()|"+CHR$(34)) THEN
FQFileSpec$ = "": EXIT FUNCTION
END IF
SELECT CASE INSTR (A$, ":")
CASE 0
IF INSTR (A$, "\") THEN
A$ = CurrentDrv$ + A$
ELSE
A$ = CurrentDrv$ + CurrentDir$ +"\"+ A$
END IF
EXIT SELECT
CASE 2
IF INSTR (A$, "\") = %False THEN
CurrentDir$ = GetCurrentDir$ (LEFT$(A$,1))
END IF
EXIT SELECT
CASE ELSE
PLAY "O0 C64": FQFileSpec$ = "": EXIT FUNCTION
END SELECT
IF INSTR (A$, "\") = %False THEN
IF RIGHT$ (A$, 1) = ":" THEN
A$ = A$ + CurrentDir$ + "\"
ELSEIF CurrentDir$ = "\" THEN
A$ = LEFT$ (A$, 2) + "\" + MID$ (A$, 3)
ELSE
A$ = LEFT$ (A$, 2) + CurrentDir$ + "\" + MID$ (A$, 3)
END IF
END IF
IF RIGHT$ (A$, 1) = "\" THEN A$ = A$ + "*.*"
REPLACE "\\" WITH "\" IN A$
FQFileSpec$ = A$
END FUNCTION ' ========= FQFileSpec$
FUNCTION Cen$ (A$) PUBLIC
Cen$ = SPACE$ (40 - LEN (A$)\2) + A$
END FUNCTION
FUNCTION CVU& (UnsignedNumRepresentation$) PUBLIC
CVU& = ASCII (LEFT$ (UnsignedNumRepresentation$, 1)) + _
256 * ASCII (MID$ (UnsignedNumRepresentation$, 2, 1))
END FUNCTION
FUNCTION MKU$ (Unsigned&) PUBLIC
Unsigned& = ABS (Unsigned&)
IF Unsigned& > 65535 THEN_
ErrorMessage$ = "APLIB: Unsigned int. Overflow": ERROR 905
MKU$ = CHR$ (Unsigned& MOD 256) + CHR$ (Unsigned& \ 256)
END FUNCTION
SUB BufferStuffer (M$) PUBLIC
IF LEN (M$) > 15 THEN PLAY "O2 E32 P8 O1 C4": M$ = "COMMAND"+CHR$(255)+"2 LONG"
L = LEN (M$)
DEF SEG = 0
POKE 1050, 30
POKE 1052, 30 + 2 * L
FOR I = 1 TO L
POKE 1052 + 2*I, ASCII (MID$ (M$,I,1))
NEXT
END SUB
FUNCTION DosVer! PUBLIC
REG %AX, &H3000
CALL INTERRUPT &H21
DosVer! = REG (%AX) MOD 256 + (REG (%AX) \ 256) / 100
END FUNCTION